import * as Vue from 'vue';
import _ from 'lodash';
import { RUNTIME_CFG_ENUM } from './Runtime/Global/variable';
import Renderer from './Runtime/Renderer/index.vue';
import DynamicComponentLoader from './ComponentLoader/dynamicComponentLoader';
import { usePrimaryStore } from '@/store';
import StorageHelper from './Runtime/Global/storage';
import { ComponentLibraryHelper } from './ComponentTemplate/componentLibrary';
import { ComponentTreeHelper } from './ComponentTemplate/componentTree';
import Notifier from './Utils/Notifier';

// for local development
import ComponentTreeNode from './ComponentTemplate/componentTree';
import { uuid } from './Utils/util';
import ComponentInstance from './ComponentTemplate/componentInstance';
import devComponent from './ComponentPackager/entry';

// global hack
import * as theme from '@CIF/Runtime/Global/theme';
import '@CIF/Runtime/Global/fake-browser-symbol-runtime.js';

// element相关
import ElementPlus from 'element-plus';
import zhCn from 'element-plus/dist/locale/zh-cn.mjs';
import * as ElementPlusIconsVue from '@element-plus/icons-vue';

// 文件分片上传
import uploader from 'vue-simple-uploader';

// 载入本地组件
import Com from '@packages/index.vue';
import { CPNT_REF_PREFIX_ENUM } from '@CIF/Runtime/Global/variable';
import data from '@packages/config/data.config.js';
import config from '@packages/config/main.config.js';

const store = usePrimaryStore();
let vm = undefined;
let cpntTree = [];

const destroy = () => {
	store.resetStore();
	Notifier.resetNotifier();
	if (vm) {
		vm.$destroy();
	}
};

/**
 *
 * @param {*} cifAppCfg
 * @param {*} componentLibrary
 *  * @param {Number} mode CIF 运行模式，枚举：PREVIEW_EDIT_MODE（预览编辑）、EDIT_MODE（组件配置/编辑）、DEV_MODE（开发）、PRODUCTION_MODE（生产）
 * @returns
 */
const configuate = (
	cifAppCfg = {
		appId: '',
		appName: '',
		referenceComponent: [],
		componentTree: '',
		engineType: '',
		baseMap: {},
		theme: {},
		mode: RUNTIME_CFG_ENUM.PRODUCTION_MODE,
		contextOptions: {},
		rendererCanvasSize: {}
	},
	componentLibrary = []
) => {
	StorageHelper.set(RUNTIME_CFG_ENUM.APPLICATION_ID, cifAppCfg.appId);
	StorageHelper.set(RUNTIME_CFG_ENUM.APPLICATION_NAME, cifAppCfg.appName);
	StorageHelper.set(RUNTIME_CFG_ENUM.APPLICATION_THEME, cifAppCfg.theme);
	StorageHelper.set(
		RUNTIME_CFG_ENUM.APPLICATION_REFRENCE_COMPONENT_CFG,
		cifAppCfg.referenceComponent
	);
	// 统一从线上获取 application config
	// StorageHelper.set(RUNTIME_CFG_ENUM.DEFAULT_ENGINE_TYPE, cifAppCfg.engineType);
	// StorageHelper.set(RUNTIME_CFG_ENUM.APPLICATION_BASEMAP, cifAppCfg.baseMap);
	StorageHelper.set(RUNTIME_CFG_ENUM.APPLICATION_COMPONENT_TREE_CFG, cifAppCfg.componentTree);
	StorageHelper.set(RUNTIME_CFG_ENUM.COMPONENT_LIBRARY_PARAM, componentLibrary);

	StorageHelper.set(RUNTIME_CFG_ENUM.CIF_RUNNING_MODE, cifAppCfg.mode);
	StorageHelper.set(RUNTIME_CFG_ENUM.CONTEXT_OPTIONS, cifAppCfg.contextOptions || {});
	StorageHelper.set(RUNTIME_CFG_ENUM.CUSTOM_RENDERER_CANVAS_SIZE, cifAppCfg.rendererCanvasSize);

	return true;
};

const validateCifConfiguration = () => {
	if (_.isNil(StorageHelper.get(RUNTIME_CFG_ENUM.APPLICATION_ID))) {
		if (_.get(window, 'cif.config.logger.enable', false) === true) {
			console.log('CIF:validateCifConfiguration ID 配置项校验失败');
		}
		return false;
	}

	if (_.isNil(StorageHelper.get(RUNTIME_CFG_ENUM.APPLICATION_NAME))) {
		if (_.get(window, 'cif.config.logger.enable', false) === true) {
			console.log('CIF:validateCifConfiguration NAME 配置项校验失败');
		}
		return false;
	}

	if (_.isNil(StorageHelper.get(RUNTIME_CFG_ENUM.COMPONENT_LIBRARY_PARAM))) {
		if (_.get(window, 'cif.config.logger.enable', false) === true) {
			console.log('CIF:validateCifConfiguration COMPONENT LIBRARY PARAM 配置项校验失败');
		}
		return false;
	}

	if (_.isNil(StorageHelper.get(RUNTIME_CFG_ENUM.APPLICATION_REFRENCE_COMPONENT_CFG))) {
		if (_.get(window, 'cif.config.logger.enable', false) === true) {
			console.log('CIF:validateCifConfiguration REFRENCE COMPONENT CFG 配置项校验失败');
		}
		return false;
	}

	if (_.isNil(StorageHelper.get(RUNTIME_CFG_ENUM.APPLICATION_COMPONENT_TREE_CFG))) {
		if (_.get(window, 'cif.config.logger.enable', false) === true) {
			console.log('CIF:validateCifConfiguration COMPONENT TREE CFG 配置项校验失败');
		}
		return false;
	}

	return true;
};

/**
 * 初始化 CIF APP
 * mode 参数决定 CIF 是否加载本地开发 package 路径下的组件
 * @param {String} mountPoint 挂载DOM的id
 * @returns
 */
const init = async (mountPoint = '') => {
	// !不能在 init 里面执行 Notifier.resetNotifier() 操作，否则一些需要提前绑定的 Notifier Listener 会失效
	store.resetStore();

	const mode = StorageHelper.get(RUNTIME_CFG_ENUM.CIF_RUNNING_MODE);
	const contextOptions = StorageHelper.get(RUNTIME_CFG_ENUM.CONTEXT_OPTIONS);

	if (!contextOptions.reuse) {
		if (vm) {
			// vm.$destroy();
			vm.unmount();
		}
	}

	let actualMountPoint = mountPoint;
	let errMsg = [];
	return new Promise((resolve = () => {}, reject = () => {}) => {
		if (!actualMountPoint) {
			reject();
			return;
		}
		if (!validateCifConfiguration()) {
			if (_.get(window, 'cif.config.logger.enable', false) === true) {
				console.log('CIF:init 未完成配置');
			}
			reject();
			return;
		}

		if (_.get(window, 'cif.config.logger.enable', false) === true) {
			console.log('CIF:init 开始初始化');
		}

		// 在此处初始化组件库和主题库资源
		// 进入到 Renderer 后应该可以直接进行渲染

		// *首先初始化组件库，获取全部组件库条目
		!contextOptions.reuse && ComponentLibraryHelper.resetLibrary();
		const cpntLibraryParam = StorageHelper.get(RUNTIME_CFG_ENUM.COMPONENT_LIBRARY_PARAM);
		const cpntLibrary = cpntLibraryParam.map((x) =>
			ComponentLibraryHelper.createAndCacheCpntLibEntry(x)
		);
		StorageHelper.set(RUNTIME_CFG_ENUM.COMPONENT_LIBRARY, cpntLibrary);

		// *组件库资源根据 CIF APP 的当前有被引用的组件进行组件定义 ComponentDefinition 和组件实例 ComponentInstance 的加载
		const cpntToBeLoad = StorageHelper.get(RUNTIME_CFG_ENUM.APPLICATION_REFRENCE_COMPONENT_CFG);

		const cpntLibEntrysToBeLoad = cpntToBeLoad
			.map((cpntRef) => {
				return ComponentLibraryHelper.getCpntLibEntryFromCache(cpntRef.componentId);
			})
			.filter((x) => !_.isEmpty(x));

		let loader = StorageHelper.get(RUNTIME_CFG_ENUM.DYNAMIC_COPONENT_LOADER);
		if (loader) {
			loader.dispose();
		}
		loader = new DynamicComponentLoader();

		StorageHelper.set(RUNTIME_CFG_ENUM.DYNAMIC_COPONENT_LOADER, loader);
		if (_.get(window, 'cif.config.logger.enable', false) === true) {
			console.log('CIF:init 开始获取远程组件');
		}

		StorageHelper.set(RUNTIME_CFG_ENUM.CIF_MODE, mode);

		// *组件编辑/配置模式不需要加载三维界面进行预览，仅需提供应用配置需要选用哪些组件的信息即可

		if (!contextOptions.reuse) {
			if (!window.Vue) window.Vue = Vue;
			vm = Vue.createApp({
				render: () => Vue.createVNode(Renderer),
				store
				// inject: ['$gTheme', '$setGTheme']
			});
			vm.provide('word', '测试');
			vm.use(ElementPlus, {
				locale: zhCn
			});
			vm.use(uploader);
			for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
				vm.component(key, component);
			}

			vm.mount(`#${actualMountPoint}`);
			window.vueInstance = vm;
			// console.log('vm', vm);
		}
		vm && theme.setGTheme(StorageHelper.get(RUNTIME_CFG_ENUM.APPLICATION_THEME));
		// vm && vm.$setGTheme(StorageHelper.get(RUNTIME_CFG_ENUM.APPLICATION_THEME));
		setTimeout(() => {
			Notifier.fireComponentStartLoadingNotification();
			loader
				.fetchAll(cpntLibEntrysToBeLoad, mode === RUNTIME_CFG_ENUM.EDIT_MODE)
				.then(([loader, fetchFailReasons]) => {
					if (_.get(window, 'cif.config.logger.enable', false) === true) {
						console.log('CIF:init 获取远程组件完毕, loader:', loader);
					}

					!_.isNil(fetchFailReasons) &&
						fetchFailReasons.length !== 0 &&
						(errMsg = errMsg.concat(fetchFailReasons));

					Notifier.notifyWhenComponentFinishLoading(() => {
						resolve([cpntTree, errMsg, vm]);
					}, 'cif_init');

					// *组件配置模式和预览模式加载全部
					if (
						mode === RUNTIME_CFG_ENUM.PREVIEW_MODE ||
						mode === RUNTIME_CFG_ENUM.EDIT_MODE ||
						mode === RUNTIME_CFG_ENUM.PRODUCTION_MODE
					) {
						if (_.get(window, 'cif.config.logger.enable', false) === true) {
							console.log('CIF:init 开始加载远程组件');
						}

						loader.loadAll(vm).then(([loadedModules, loadFailReasons]) => {
							if (_.get(window, 'cif.config.logger.enable', false) === true) {
								console.log('CIF:init 加载组件完毕, modules:', loadedModules);
							}
							const cpntTreeParam = StorageHelper.get(
								RUNTIME_CFG_ENUM.APPLICATION_COMPONENT_TREE_CFG
							);
							if (_.get(window, 'cif.config.logger.enable', false) === true) {
								console.log('CIF:init 开始初始化组件图层树');
							}
							cpntTree = ComponentTreeHelper.initTree(cpntTreeParam);
							if (_.get(window, 'cif.config.logger.enable', false) === true) {
								console.log('CIF:init 初始化组件图层树完毕, cpntTree:', cpntTree);
							}
							// StorageHelper.set(RUNTIME_CFG_ENUM.APPLICATION_COMPONENT_TREE, cpntTree);
							store.updateTree(cpntTree);
							Notifier.fireComponentFinishLoadingNotification();
							!_.isNil(loadFailReasons) &&
								loadFailReasons.length !== 0 &&
								(errMsg = errMsg.concat(loadFailReasons));
							return;
						});
					}

					// *开发模式下加载本地组件代码，面向 connector 来做 build 的时候需要注释掉，否则会因找不到 package 文件夹而报错
					if (mode === RUNTIME_CFG_ENUM.DEV_MODE) {
						const cpntDefId = uuid();
						if (_.get(window, 'cif.config.logger.enable', false) === true) {
							console.log('CIF:init 开始加载本地组件');
						}

						loader.loadLocal(vm, devComponent, cpntDefId); // 加载本地组件并生成组件定义
						if (_.get(window, 'cif.config.logger.enable', false) === true) {
							console.log('CIF:init 加载本地组件完毕');
						}
						cpntTree = ComponentTreeHelper.getNewTree();
						const cpntInstance = new ComponentInstance({ definitionId: cpntDefId });
						const treeNodeData = {
							uuid: cpntInstance.uuid,
							name: cpntInstance.name,
							nodeType: cpntInstance.definitionRefrence.cpntType,
							componentInstance: cpntInstance
						};
						const cpntTreeNode = new ComponentTreeNode(treeNodeData);
						cpntTreeNode.__local = true;

						ComponentTreeHelper.addTreeNodeToTree(cpntTree, cpntTreeNode);
						// StorageHelper.set(RUNTIME_CFG_ENUM.APPLICATION_COMPONENT_TREE, cpntTree);
						store.updateTree(cpntTree);
						StorageHelper.set(RUNTIME_CFG_ENUM.CIF_MODE, mode);
						Notifier.fireComponentFinishLoadingNotification();
						return;
					}
				})
				.catch((errorOnLoad) => {
					reject(errorOnLoad);
				});
		}, 0);
	});
};

export default {
	configuate,
	init,
	destroy
};
